package com.example.testplatform.service.impl;

import com.example.testplatform.common.LogUtils;
import com.example.testplatform.mapper.RoleMenuMapper;
import com.example.testplatform.service.RoleMenuService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class RoleMenuServiceImpl implements RoleMenuService {
    
    private static final Logger logger = LogUtils.getLogger(RoleMenuServiceImpl.class);
    
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    
    @Override
    public List<Long> getMenuIdsByRoleId(Long roleId) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "ROLE_MENU_QUERY_START", "system", "准备根据角色ID查询菜单ID列表，角色ID: " + roleId);
        try {
            // 参数验证
            if (roleId == null || roleId <= 0) {
                LogUtils.warn(logger, "【角色菜单管理】getMenuIdsByRoleId方法参数验证失败: 角色ID为空或非法值: " + roleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_QUERY_FAILED", "system", "根据角色ID查询菜单ID列表参数验证失败: " + roleId);
                return null;
            }
            
            LogUtils.debug(logger, () -> "【角色菜单管理】开始执行getMenuIdsByRoleId方法，角色ID: " + roleId);
            LogUtils.debug(logger, () -> "【角色菜单管理】开始计时，当前时间戳: " + startTime);
            
            LogUtils.debug(logger, () -> "【角色菜单管理】调用roleMenuMapper.findMenuIdsByRoleId方法查询数据库，角色ID: " + roleId);
            List<Long> menuIds = roleMenuMapper.findMenuIdsByRoleId(roleId);
            
            LogUtils.debug(logger, () -> "【角色菜单管理】数据库查询完成，开始处理查询结果");
            if (menuIds == null) {
                LogUtils.debug(logger, () -> "【角色菜单管理】查询结果为空集合，返回空列表");
                menuIds = java.util.Collections.emptyList();
            }
            
            // 创建final变量供lambda表达式使用
            final List<Long> finalMenuIds = menuIds;
            final Long finalRoleId = roleId;
            
            LogUtils.info(logger, () -> "【角色菜单管理】根据角色ID " + finalRoleId + " 查询菜单ID列表成功，共 " + finalMenuIds.size() + " 个菜单");
            LogUtils.logBusiness(logger, "ROLE_MENU_QUERY_SUCCESS", "system", "根据角色ID " + finalRoleId + " 查询菜单ID列表成功，菜单数量: " + finalMenuIds.size());
            
            LogUtils.logPerformance(logger, "getMenuIdsByRoleId", startTime, System.currentTimeMillis());
            LogUtils.debug(logger, () -> "【角色菜单管理】getMenuIdsByRoleId方法执行完成，返回菜单ID列表");
            return menuIds;
        } catch (Exception e) {
            LogUtils.error(logger, "【角色菜单管理】根据角色ID查询菜单ID列表异常: " + roleId + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "ROLE_MENU_QUERY_ERROR", "system", "根据角色ID查询菜单ID列表发生异常: " + roleId + ", " + e.getMessage());
            throw e;
        }
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean assignMenusToRole(Long roleId, List<Long> menuIds) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_ATTEMPT", "system", "为角色分配菜单尝试开始");
        
        // 创建final本地变量供lambda表达式使用，移到try块外部确保作用域覆盖整个方法
        final Long finalRoleId = roleId;
        final List<Long> finalMenuIds = menuIds;
        
        try {
            // 参数验证
            if (finalRoleId == null || finalRoleId <= 0) {
                LogUtils.warn(logger, "【角色菜单管理】assignMenusToRole方法参数验证失败: 角色ID为空或非法值: " + finalRoleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_FAILED", "system", "为角色分配菜单参数验证失败: 角色ID非法");
                return false;
            }
            
            LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_PROCESS", "system", "为角色分配菜单处理开始: 角色ID=" + finalRoleId + ", 菜单数量=" + (finalMenuIds != null ? finalMenuIds.size() : 0));
            LogUtils.debug(logger, () -> "【角色菜单管理】开始执行assignMenusToRole方法为角色分配菜单: 角色ID=" + finalRoleId + ", 菜单数量=" + (finalMenuIds != null ? finalMenuIds.size() : 0));
            LogUtils.debug(logger, () -> "【角色菜单管理】开始计时，当前时间戳: " + startTime);
            
            // 先删除原有关联
            LogUtils.debug(logger, () -> "【角色菜单管理】开始删除角色原有的菜单关联: " + finalRoleId);
            int deleteCount = roleMenuMapper.deleteByRoleId(finalRoleId);
            LogUtils.debug(logger, () -> "【角色菜单管理】角色原有菜单关联删除成功: " + finalRoleId + ", 删除数量: " + deleteCount);
            LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_DELETE_OLD", "system", "删除角色原有菜单关联成功: 角色ID=" + finalRoleId + ", 删除数量: " + deleteCount);
            
            // 批量添加新关联
            final boolean[] result = {true};
            if (finalMenuIds != null && !finalMenuIds.isEmpty()) {
                LogUtils.debug(logger, () -> "【角色菜单管理】开始批量添加新的菜单关联: " + finalRoleId + ", 菜单数量: " + finalMenuIds.size());
                LogUtils.debug(logger, () -> "【角色菜单管理】菜单ID列表: " + finalMenuIds);
                
                int insertCount = roleMenuMapper.batchInsert(finalRoleId, finalMenuIds);
                result[0] = insertCount > 0;
                
                LogUtils.debug(logger, () -> "【角色菜单管理】批量添加新的菜单关联完成: " + finalRoleId + ", 插入数量: " + insertCount + ", 结果: " + result[0]);
                LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_INSERT_NEW", "system", "批量添加新的菜单关联完成: 角色ID=" + finalRoleId + ", 插入数量: " + insertCount);
            } else {
                LogUtils.debug(logger, () -> "【角色菜单管理】菜单ID列表为空，不添加新的关联: " + finalRoleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_NO_MENUS", "system", "菜单ID列表为空，不添加新的关联: 角色ID=" + finalRoleId);
            }
            
            if (result[0]) {
                LogUtils.info(logger, () -> "【角色菜单管理】为角色分配菜单成功: 角色ID=" + finalRoleId + ", 菜单数量=" + (finalMenuIds != null ? finalMenuIds.size() : 0));
                LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_SUCCESS", "system", "为角色分配菜单成功: 角色ID=" + finalRoleId + ", 菜单数量=" + (finalMenuIds != null ? finalMenuIds.size() : 0));
            } else {
                LogUtils.warn(logger, "【角色菜单管理】为角色分配菜单失败: 角色ID={}", finalRoleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_FAILED", "system", "为角色分配菜单失败: 角色ID=" + finalRoleId);
            }
            
            LogUtils.logPerformance(logger, "assignMenusToRole", startTime, System.currentTimeMillis());
            LogUtils.debug(logger, () -> "【角色菜单管理】assignMenusToRole方法执行完成，结果: " + result[0]);
            return result[0];
        } catch (Exception e) {
            LogUtils.error(logger, "【角色菜单管理】为角色分配菜单异常: 角色ID=" + finalRoleId + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "ROLE_MENU_ASSIGN_ERROR", "system", "为角色分配菜单发生异常: 角色ID=" + finalRoleId + ", " + e.getMessage());
            throw e;
        }
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeAllMenusFromRole(Long roleId) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_ATTEMPT", "system", "移除角色所有菜单尝试开始");
        try {
            // 参数验证
            if (roleId == null || roleId <= 0) {
                LogUtils.warn(logger, "【角色菜单管理】removeAllMenusFromRole方法参数验证失败: 角色ID为空或非法值: " + roleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_FAILED", "system", "移除角色所有菜单参数验证失败: 角色ID非法");
                return false;
            }
            
            LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_PROCESS", "system", "移除角色所有菜单处理开始: 角色ID=" + roleId);
            LogUtils.debug(logger, () -> "【角色菜单管理】开始执行removeAllMenusFromRole方法移除角色所有菜单: " + roleId);
            LogUtils.debug(logger, () -> "【角色菜单管理】开始计时，当前时间戳: " + startTime);
            
            LogUtils.debug(logger, () -> "【角色菜单管理】调用roleMenuMapper.deleteByRoleId方法删除数据库关联记录，角色ID: " + roleId);
            int deleteCount = roleMenuMapper.deleteByRoleId(roleId);
            boolean result = deleteCount > 0;
            
            LogUtils.debug(logger, () -> "【角色菜单管理】数据库删除完成，删除数量: " + deleteCount + ", 结果: " + result);
            if (result) {
                LogUtils.info(logger, () -> "【角色菜单管理】移除角色所有菜单成功: " + roleId + ", 移除数量: " + deleteCount);
                LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_SUCCESS", "system", "移除角色所有菜单成功: 角色ID=" + roleId + ", 移除数量: " + deleteCount);
            } else {
                LogUtils.warn(logger, "【角色菜单管理】移除角色所有菜单失败: 角色ID={}, 原因: 角色不存在或没有关联的菜单", roleId);
                LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_FAILED", "system", "移除角色所有菜单失败: 角色ID=" + roleId);
            }
            
            LogUtils.logPerformance(logger, "removeAllMenusFromRole", startTime, System.currentTimeMillis());
            LogUtils.debug(logger, () -> "【角色菜单管理】removeAllMenusFromRole方法执行完成，结果: " + result);
            return result;
        } catch (Exception e) {
            LogUtils.error(logger, "【角色菜单管理】移除角色所有菜单异常: 角色ID=" + roleId + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "ROLE_MENU_REMOVE_ALL_ERROR", "system", "移除角色所有菜单发生异常: 角色ID=" + roleId + ", " + e.getMessage());
            throw e;
        }
    }
    
    @Override
    public boolean checkPermission(Long roleId, Long menuId) {
        long startTime = System.currentTimeMillis();
        LogUtils.logBusiness(logger, "ROLE_PERMISSION_CHECK_START", "system", "准备检查角色菜单权限: 角色ID=" + roleId + ", 菜单ID=" + menuId);
        try {
            // 参数验证
            if (roleId == null || roleId <= 0) {
                LogUtils.warn(logger, "【角色菜单管理】checkPermission方法参数验证失败: 角色ID为空或非法值: " + roleId);
                LogUtils.logBusiness(logger, "ROLE_PERMISSION_CHECK_FAILED", "system", "检查角色菜单权限参数验证失败: 角色ID非法");
                return false;
            }
            if (menuId == null || menuId <= 0) {
                LogUtils.warn(logger, "【角色菜单管理】checkPermission方法参数验证失败: 菜单ID为空或非法值: " + menuId);
                LogUtils.logBusiness(logger, "ROLE_PERMISSION_CHECK_FAILED", "system", "检查角色菜单权限参数验证失败: 菜单ID非法");
                return false;
            }
            
            LogUtils.debug(logger, () -> "【角色菜单管理】开始执行checkPermission方法检查角色菜单权限: 角色ID=" + roleId + ", 菜单ID=" + menuId);
            LogUtils.debug(logger, () -> "【角色菜单管理】开始计时，当前时间戳: " + startTime);
            
            LogUtils.debug(logger, () -> "【角色菜单管理】调用roleMenuMapper.checkPermission方法查询数据库权限记录");
            Integer count = roleMenuMapper.checkPermission(roleId, menuId);
            boolean hasPermission = count != null && count > 0;
            
            LogUtils.debug(logger, () -> "【角色菜单管理】数据库查询完成，角色ID=" + roleId + ", 菜单ID=" + menuId + ", 查询结果数量: " + (count != null ? count : 0));
            LogUtils.info(logger, () -> "【角色菜单管理】角色菜单权限检查结果: 角色ID=" + roleId + ", 菜单ID=" + menuId + ", 有权限: " + hasPermission);
            LogUtils.logBusiness(logger, "ROLE_PERMISSION_CHECK_RESULT", "system", "角色菜单权限检查结果: 角色ID=" + roleId + ", 菜单ID=" + menuId + ", 有权限: " + hasPermission);
            
            LogUtils.logPerformance(logger, "checkPermission", startTime, System.currentTimeMillis());
            LogUtils.debug(logger, () -> "【角色菜单管理】checkPermission方法执行完成，返回权限检查结果");
            return hasPermission;
        } catch (Exception e) {
            LogUtils.error(logger, "【角色菜单管理】检查角色菜单权限异常: 角色ID=" + roleId + ", 菜单ID=" + menuId + ", 错误: " + LogUtils.formatException(e));
            LogUtils.logBusiness(logger, "ROLE_PERMISSION_CHECK_ERROR", "system", "检查角色菜单权限发生异常: 角色ID=" + roleId + ", 菜单ID=" + menuId + ", " + e.getMessage());
            throw e;
        }
    }
}